package serveur;

import static org.junit.Assert.assertTrue;

import java.util.ArrayList;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.Modifier;

import org.junit.Test;

/**
 * Classe de test de la classe CallMethod
 * @author Kevin Pozderec,Faycal Abka
 *
 */
public class TestCallMethod {

	@Test
	public void testCallMethod_call_pointMove1() {		
	
		/*Création d'un objet Point avec Javassist*/
		
		/*fait un pointMove pour passer de x=86 et y=133 à x=16 y=74*/
		int xtest=-15,ytest=58,oidtest=116;
		int newX=525,newY=3;
		
		try {

		ArrayList<CtClass>listeClasse = new ArrayList<CtClass>();
		ArrayList<Object>listeArg = new ArrayList<Object>();
		ClassPool def = ClassPool.getDefault();
		CtClass obj_point_class = def.makeClass("Objet_testCallMethod_call_pointMove_Point1");
		
		CtField prop_x = new CtField(CtClass.intType, "x", obj_point_class);		
		CtField prop_y = new CtField(CtClass.intType, "y", obj_point_class);
		CtField oid = new CtField(CtClass.intType, "__oid", obj_point_class);
		
		CtField type = CtField.make(
				"public String __type = \"IPoint\";", obj_point_class);	

		
		prop_x.setModifiers(Modifier.PUBLIC);
		prop_y.setModifiers(Modifier.PUBLIC);
		oid.setModifiers(Modifier.PUBLIC);
		
		obj_point_class.addField(prop_x,""+xtest);
		obj_point_class.addField(prop_y,""+ytest);
		obj_point_class.addField(oid,""+oidtest);
		obj_point_class.addField(type);

		
		CtMethod meth_getX = CtNewMethod.make("public int getX(){ return x;}", obj_point_class);
		CtMethod meth_getY = CtNewMethod.make("public int getY(){ return y;}", obj_point_class);
		CtMethod meth_setX = CtNewMethod.make("public void setX(int i){ this.x=i;}", obj_point_class);
		CtMethod meth_setY = CtNewMethod.make("public void setY(int i){ this.y=i;}", obj_point_class);
		
		obj_point_class.addMethod(meth_getX);
		obj_point_class.addMethod(meth_getY);
		obj_point_class.addMethod(meth_setX);
		obj_point_class.addMethod(meth_setY);
		
		//obj_point_class.addInterface(def.makeInterface("objet.IPoint"));
		
		listeClasse.add(obj_point_class);	
		listeArg.add(new Integer(newX));
		listeArg.add(new Integer(newY));

		
		String result = CallMethod.call("pointMove", listeClasse, null , listeArg, def, new InvokedMethodsImpl());
		String expected = "<methodResponse><params><param><value>void</value></param><param><value><object oid=\""+oidtest+"\" type=\"IPoint\"><fields><field name=\"x\"><value><int>"+newX+"</int></value></field><field name=\"y\"><value><int>"+newY+"</int></value></field></fields><methods></methods></object></value></param></params></methodResponse>\r\n";
				
		
		if ( result.equals(expected) ){
			assertTrue(true);
			obj_point_class.detach();

			return;
		}
		
		System.err.println("Ce n'est pas la chaîne attendue.");
		System.err.println("Chaîne attendue = "+expected);
		System.err.println("Chaîne résultat = "+result);
		
		assertTrue(false);		
		
		obj_point_class.detach();

		
		} catch (CannotCompileException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		
		assert(false);
	}
	
	@Test
	public void testCallMethod_call_pointMove2() {		
	
		/*Création d'un objet Point avec Javassist*/
		
		/*fait un pointMove pour passer de x=86 et y=133 à x=16 y=74*/
		int xtest=86,ytest=133,oidtest=10;
		int newX=16,newY=74;
		
		try {

		ArrayList<CtClass>listeClasse = new ArrayList<CtClass>();
		ArrayList<Object>listeArg = new ArrayList<Object>();
		ClassPool def = ClassPool.getDefault();
		CtClass obj_point_class = def.makeClass("Objet_testCallMethod_call_pointMove_Point2");
		
		CtField prop_x = new CtField(CtClass.intType, "x", obj_point_class);		
		CtField prop_y = new CtField(CtClass.intType, "y", obj_point_class);
		CtField oid = new CtField(CtClass.intType, "__oid", obj_point_class);
		
		CtField type = CtField.make(
				"public String __type = \"IPoint\";", obj_point_class);	

		
		prop_x.setModifiers(Modifier.PUBLIC);
		prop_y.setModifiers(Modifier.PUBLIC);
		oid.setModifiers(Modifier.PUBLIC);
		
		obj_point_class.addField(prop_x,""+xtest);
		obj_point_class.addField(prop_y,""+ytest);
		obj_point_class.addField(oid,""+oidtest);
		obj_point_class.addField(type);

		
		CtMethod meth_getX = CtNewMethod.make("public int getX(){ return x;}", obj_point_class);
		CtMethod meth_getY = CtNewMethod.make("public int getY(){ return y;}", obj_point_class);
		CtMethod meth_setX = CtNewMethod.make("public void setX(int i){ this.x=i;}", obj_point_class);
		CtMethod meth_setY = CtNewMethod.make("public void setY(int i){ this.y=i;}", obj_point_class);
		
		obj_point_class.addMethod(meth_getX);
		obj_point_class.addMethod(meth_getY);
		obj_point_class.addMethod(meth_setX);
		obj_point_class.addMethod(meth_setY);
		
		//obj_point_class.addInterface(def.makeInterface("objet.IPoint"));
		
		listeClasse.add(obj_point_class);	
		listeArg.add(new Integer(newX));
		listeArg.add(new Integer(newY));

		
		String result = CallMethod.call("pointMove", listeClasse, null , listeArg, def, new InvokedMethodsImpl());
		String expected = "<methodResponse><params><param><value>void</value></param><param><value><object oid=\""+oidtest+"\" type=\"IPoint\"><fields><field name=\"x\"><value><int>"+newX+"</int></value></field><field name=\"y\"><value><int>"+newY+"</int></value></field></fields><methods></methods></object></value></param></params></methodResponse>\r\n";
				
		
		if ( result.equals(expected) ){
			assertTrue(true);
			obj_point_class.detach();

			return;
		}
		
		System.err.println("Ce n'est pas la chaîne attendue.");
		System.err.println("Chaîne attendue = "+expected);
		System.err.println("Chaîne résultat = "+result);
		
		assertTrue(false);		
		
		obj_point_class.detach();

		
		} catch (CannotCompileException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		
		assert(false);
	}
	
	@Test
	public void testCallMethod_call_useObject1(){
		
		/*Création d'un objet Objet1 avec Javassist*/
			
		try {
			ArrayList<CtClass>listeClasse = new ArrayList<CtClass>();
			ArrayList<Object>listeArg = new ArrayList<Object>();
			ClassPool def = ClassPool.getDefault();
			CtClass obj_objet1_class = def.makeClass("Objet_testCallMethod_call_useObject1_Objet1");		
			
			
			CtField oid = new CtField(CtClass.intType, "__oid", obj_objet1_class);	
			CtField type = CtField.make(
					"public String __type = \"IObjet1\";", obj_objet1_class);	
			
			
			oid.setModifiers(Modifier.PUBLIC);			
			obj_objet1_class.addField(oid,"1234");
			obj_objet1_class.addField(type);

			
			CtMethod meth_affiche = CtNewMethod.make("public String affiche(int a, boolean b, String c, double d){ return \"a=\"+a+\",b=\"+b+\",c=\"+c+\",d=\"+d;}", obj_objet1_class);		
			obj_objet1_class.addMethod(meth_affiche);	
			
			listeClasse.add(obj_objet1_class);	
			
			listeArg.add(new Integer(14));
			listeArg.add(new Boolean(true));
			listeArg.add("test texte");
			listeArg.add(new Double(15.6));
			
			String result = CallMethod.call("useObject1", listeClasse, null , listeArg, def, new InvokedMethodsImpl());
			String expected = "<methodResponse><params><param><value><string>a=14,b=true,c=test texte,d=15.6</string></value></param><param><value><object oid=\"1234\" type=\"IObjet1\"><fields></fields><methods></methods></object></value></param></params></methodResponse>\r\n";
			
		
			if ( result.equals(expected) ){
				assertTrue(true);
				obj_objet1_class.detach();

				return;
			}
			assertTrue(false);		
			
			
		} catch (CannotCompileException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}				
	}

}
